import processing.core.*;

/**
 * @author Tiina, Chris, Lauri
 *
 * Luokka kuvaa lennon piirtämistä ohjelmassa ja lennon aikana tapahtuvia asioita.
 */

public class Reitti {

	private float x1, y1;//Lähtöpiste
	private float x2, y2;//Määränpää
	private float w, wi;//Koneen maksimikoko ja dynaaminen koko
	
	private float kesto;//Lennon kesto
	private float luotu;//Lennon luoomisaika
	private PImage kuva;
	private float alkukulma;//Kts. konstruktorin ohje
	
	public boolean saapunut = false;
	public boolean loppu = false;
	
	private float kaanto;//Mihin suuntaan koneen nokka osoittaa
	private UserInterface p;
	private Lento lentotiedot; //Lento, joka reitillä on
	private boolean lightWasOn;
	
	public float currentX, currentY; //Missä kohtaa mennään

	/**
	 *		  Konstruktori uudelle reitille
	 *		  Parametrit järjestyksessä:
	 *		  lähtöpisteen x, lähtöpisteen y,
	 *		  kohdepisteen x, kohdepisteen y,
	 *		  kuvan leveys, kuvan korkeus,
	 *		  matkan kesto (ms),
	 *		  tiedoston nimi muodossa "kuvatiedostonnimi.jpg",
	 *		  kulma = kuinka monta radiaania kuvan konetta pitaa kaantaa,
	 *		  etta sen nokka on kohti itaa
	 */
	public Reitti(float lahtoX, float lahtoY, float kohdeX, float kohdeY, float leveys, float korkeus, float aika, String tiedosto, float alkukulma, UserInterface parent)
	{
		this.p = parent;
		x1 = lahtoX;
		y1 = lahtoY;
		x2 = kohdeX;
		y2 = kohdeY;
		w = leveys;
		kesto = aika;
		luotu = p.millis(); //Luomisaika
		kuva = p.loadImage(tiedosto);
		this.alkukulma = alkukulma;
		
		//Lentokoneen kaantokulman laskeminen
		float kulma = (y2-y1)/(x2-x1);
		kaanto = alkukulma+PApplet.atan(kulma);
		if(x2<x1) kaanto += PApplet.PI;
	}

	//Kevyempi versio konstruktorista, koska osa parametreista on staattisia.
	public Reitti(float kohdeX, float kohdeY, float aika, UserInterface parent, Lento lentotiedot)
	{
		this.p = parent;
		
		// Helsingin sijainti on staattinen: 625,172
		x1 = 625;
		y1 = 172;
		x2 = kohdeX;
		y2 = kohdeY;
		
		// Lentokoneet ovat samankokoisia
		w = 30;
		kesto = aika*60*15 / this.p.annaNopeuskerroin();
		luotu = p.millis(); //Luomisaika
		kuva = p.loadImage("lentokone4.png"); // Aina sama lentokone
		this.alkukulma = (float) (0.5*PApplet.PI);
		
		//Lentokoneen kaantokulman laskeminen
		float kulma = (y2-y1)/(x2-x1);
		kaanto = alkukulma+PApplet.atan(kulma);
		if(x2<x1) kaanto += PApplet.PI;
		this.lentotiedot = lentotiedot;
	}

	/*Palautetaan lennon lentotiedot*/
	public Lento getLentotiedot() {
		return this.lentotiedot;
	}

	float getDestX() {
		return this.x2;
	}

	float getDestY() {
		return this.y2;
	}
	

	/*Metodi, jossa konetta piirretään reitillään. Päivittyy jatkuvasti.*/
	public void draw()
	{
		//Koneen siirtymät
		float a = x2-x1;
		float b = y2-y1;
		
		//Aika menee 0 -> 1 lennon alusta loppuun
		float aika = (p.millis()-luotu)/kesto;
		
		if(aika<=1){

			p.stroke(200,0,0,50);
			p.strokeWeight(1);
			currentX = x1+aika*a;
			currentY = y1+aika*b;
			
			//Kone ei ole saapunut päämäärään
			if(!saapunut){

				p.line(x1, y1, currentX, currentY);
				if(PApplet.dist(p.mouseX, p.mouseY, currentX, currentY)<15) // Hiiri on koneen yläpuolella
				{ 

					if (p.lightOn == null) {
						p.lightOn = this; // Lukitaan valo omaan käyttöön
						this.lightWasOn = true; // Muistetaan, että meillä on yksinoikeus valoon
						
						
						// Kerrotaan UI:lle, että piirtää puhekuplan tämän koneen kohdalle
						p.drawThisDestination = this;

					}

				}
				else if (p.lightOn != null && this.lightWasOn){
					p.lightOn = null; // Vapautetaan valo muiden käyttöön
					this.lightWasOn = false; // Unohdetaan oma valo
					p.drawThisDestination = null; // Kerrotaan UI:lle, ettei tarvitse piirtää puhekuplaa
				}
				p.pushMatrix();
				p.translate(currentX, currentY);
				p.rotate(kaanto);
				lentokone(currentX, currentY);
				p.popMatrix();
			}
			
			//Kone on saapunut, mutta näkyy vielä vähän aikaa.
			else if(!loppu)
			{
				currentX = x1+aika*10*a;
				currentY = y1+aika*10*b;
				p.line(currentX, currentY, x2, y2);
				p.pushMatrix();
				p.translate(x2, y2);
				p.rotate(kaanto);
				lentokone(0,0);
				p.popMatrix();
				
				//Viiva ja kone kadotetaan, kun aika on alkanut uudestaan ja on yli 0.1
				if(aika>0.1) {

					this.lentotiedot.setMidAir(false);
					if (this.lightWasOn) {
						p.lightOn = null; // Vapautetaan valo muiden käyttöön
						p.drawThisDestination = null; // Kerrotaan UI:lle, ettei tarvitse piirtää puhekuplaa
					}
					loppu = true;
				}
			}

		}
		
		//Aika on suurempi ku 1
		else{
			if(saapunut) {
				loppu =true;
			}
			if (this.lightWasOn) {
				p.lightOn = null; // Vapautetaan valo muiden käyttöön
				p.drawThisDestination = null; // Kerrotaan UI:lle, ettei tarvi piirtää puhekuplaa
			}
			this.lentotiedot.setMidAir(false);
			saapunut = true;
			p.pushMatrix();
			p.translate(x2, y2);
			p.rotate(kaanto);
			lentokone(0,0);
			p.popMatrix();
			luotu=p.millis();
		} 
	}
	
	//Piirretään lentokone ja sen vilkkuvat valot
	void lentokone(float currentX, float currentY)
	{
		//Koneen piirto
		wi = w;
		float dist1 = PApplet.dist(x1, y1, currentX, currentY);
		float dist2 = PApplet.dist(x2, y2, currentX, currentY);
		if(dist1<30)
		{
			wi=w-20*(30-dist1)/30;
		}
		if(dist2<30)
		{
			wi=wi-20*(30-dist2)/30;
		}
		
		if(saapunut || wi<10) wi = 10;
		p.image(kuva, 0, 0, wi, wi);
		
		//Vilkkuvat valot
		p.noStroke();
		p.ellipseMode(PApplet.CENTER);
		float apu = PApplet.abs(PApplet.sin(p.millis()/100))*255;
		float apu2 = PApplet.abs(PApplet.sin(p.millis()/700))*255;
		p.fill(255,100,150,apu);
		p.ellipse(-wi/5,0,wi/15,wi/15);
		p.fill(100,255,150,apu);
		p.ellipse(wi/5,0,wi/15,wi/15);
		p.fill(200,255,255,apu2);
		p.ellipse(0,(float) (wi/2.3),wi/12,wi/12);
		p.ellipse((float) (wi/2.7), wi/10, wi/12, wi/12);
		p.ellipse((float) (-wi/2.7), wi/10, wi/12, wi/12);

	}
	
	/*Valaistaan koneen ympäristö (kätevää erityisesti yöllä).*/
	void valaise()
	{
		int xp =(int)currentX;
		int yp =(int)currentY;
		int alue = 80;
		for (int x = xp-alue; x < xp+alue; x++ ) {
			for (int y = yp-alue; y < yp+alue; y++ ) {  
				
				//Lasketaan pikselin 1D-koordinaatti
				int loc = x + y*p.width;
				if(loc>0 && loc<p.width*p.height)
				{
					//RGB-arvot kuvalle
					float r = p.red (p.pixels[loc]);
					float g = p.green (p.pixels[loc]);
					float b = p.blue (p.pixels[loc]);
					float distance = PApplet.dist(x,y,xp,yp);
					float adjustBrightness = 1+(alue-distance)/alue;
					if(adjustBrightness<1)
						adjustBrightness = 1;

					r *= adjustBrightness;
					g *= adjustBrightness;
					b *= adjustBrightness;


					//RGB välille 0-255
					r = PApplet.constrain(r,0,255);
					g = PApplet.constrain(g,0,255);
					b = PApplet.constrain(b,0,255);

					//Luodaan uusi väri ja asetetaan näytölle
					p.pixels[loc] = p.color(r,g,b);
				}
			}
		}
	}
}